#ifndef __DDRC_H__
#define __DDRC_H__

#include <base.h>
#include <cpm.h>

#define CONFIG_DDR_INNOPHY
struct size {
	unsigned int chip0;
	unsigned int chip1;
};

#define ddr_common_params			\
	unsigned int tRAS;				\
	unsigned int tRP;				\
	unsigned int tRCD;				\
	unsigned int tRC;				\
	unsigned int tWR;				\
	unsigned int tRRD;				\
	unsigned int tWTR;				\
	unsigned int tRFC;				\
	unsigned int tXP;				\
	unsigned int tCKE;				\
	unsigned int RL;				\
	unsigned int WL;				\
	unsigned int tREFI;

struct ddr3_params {
	ddr_common_params;
	unsigned int tCKESR;
	unsigned int tCKSRE;
	unsigned int tXSDLL;
	unsigned int tMOD;
	unsigned int tXPDLL;
	unsigned int tXS;
	unsigned int tRTP;
	unsigned int tCCD;
	unsigned int tFAW;
	unsigned int tMRD;
};

struct ddr2_params {
	ddr_common_params;
	unsigned int tCKESR;
	unsigned int tCWL;
	unsigned int tXSNR;
	unsigned int tXARD;
	unsigned int tXARDS;
	unsigned int tXSRD;
	unsigned int tRTP;
	unsigned int tCCD;
	unsigned int tFAW;
	unsigned int tMRD;
};

struct lpddr3_params {
	ddr_common_params;
	unsigned int tCKESR;
	unsigned int tXSR;
	unsigned int tMOD;
	unsigned int tDQSCK;
	unsigned int tDQSCKMAX;
	unsigned int tRTP;
	unsigned int tCCD;
	unsigned int tFAW;
	unsigned int tMRD;
};

struct lpddr2_params {
	ddr_common_params;
	unsigned int tCKESR;
	unsigned int tXSR;
	unsigned int tMOD;
	unsigned int tDQSCK;
	unsigned int tDQSCKMAX;
	unsigned int tRTP;
	unsigned int tCCD;
	unsigned int tFAW;
	unsigned int tMRD;
};

struct lpddr_params {
	ddr_common_params;
	unsigned int tMRD;
	unsigned int tDQSSMAX;
	unsigned int tXSR;

};
struct ddr_params_common
{
	ddr_common_params;
};

union private_params {
	struct ddr_params_common ddr_base_params;
	struct ddr3_params ddr3_params;
	struct lpddr_params lpddr_params;
	struct lpddr2_params lpddr2_params;
	struct lpddr3_params lpddr3_params;
	struct ddr2_params  ddr2_params;
};

#ifdef CONFIG_DDR_INNOPHY
union ddr_mr0 {
	/** raw register data */
	unsigned int d32;
	/** register bits */
	struct {
		unsigned BL:2;
		unsigned CL_2:1;
		unsigned BT:1;
		unsigned CL_4_6:3;
		unsigned TM:1;
		unsigned DR:1;
		unsigned WR:3;
		unsigned PD:1;
		unsigned RSVD13_15:3;
		unsigned BA:2;
		unsigned RSVD_BA:1;
		unsigned reserved19_31:13;
	} ddr3; /* MR0 */
};

union ddr_mr1 {
	/** raw register data */
	unsigned int d32;
	/** register bits */
	struct {
		unsigned DE:1;
		unsigned DIC1:1;
		unsigned RTT2:1;
		unsigned AL:2;
		unsigned DIC5:1;
		unsigned RTT6:1;
		unsigned LEVEL:1;
		unsigned RSVD8:1;
		unsigned RTT9:1;
		unsigned RSVD10:1;
		unsigned TDQS:1;
		unsigned QOFF:1;
		unsigned RSVD13_15:3;
		unsigned BA:2;
		unsigned RSVD_BA:1;
		unsigned reserved19_31:13;
	} ddr3; /* MR1 */
	struct {
		unsigned BL:3;
		unsigned BT:1;
		unsigned WC:1;
		unsigned nWR:3;
		unsigned MA:8;
		unsigned reserved16_31:16;
	} lpddr2; /* MR1 */
	struct {
		unsigned BL:3;
		unsigned RSVD3_4:2;
		unsigned nWR:3;
		unsigned MA:8; //should 10 bit
		unsigned reserved16_31:16;
	} lpddr3; /* MR1 */
};

union ddr_mr2 {
	/** raw register data */
	unsigned int d32;
	/** register bits */
	struct {
		unsigned PASR:3;
		unsigned CWL:3;
		unsigned ASR:1;
		unsigned SRT:1;
		unsigned RSVD8:1;
		unsigned RTTWR:2;
		unsigned RSVD11_15:5;
		unsigned BA:2;
		unsigned RSVD_BA:1;
		unsigned reserved19_31:13;
	} ddr3; /* MR2 */
	struct {
		unsigned RL_WL:4;
		unsigned RSVD4_7:4;
		unsigned MA:8;
		unsigned reserved16_31:16;
	} lpddr2; /* MR2 */
	struct {
		unsigned RL_WL:4;
		unsigned WRE:1;
		unsigned RSVD5:1;
		unsigned WL_S:1;
		unsigned WR_L:1;
		unsigned MA:8;
		unsigned reserved16_31:16;
	} lpddr3; /* MR2 */
};

union ddr_mr3 {
	/** raw register data */
	unsigned int d32;
	/** register bits */
	struct {
		unsigned MPRLOC:2;
		unsigned MPR:1;
		unsigned RSVD3_15:13;
		unsigned BA:2;
		unsigned RSVD_BA:1;
		unsigned reserved19_31:13;
	} ddr3; /* MR3 */
	struct {
		unsigned DS:4;
		unsigned RSVD4_7:4;
		unsigned MA:8;
		unsigned reserved16_31:16;
	} lpddr2; /* MR3 */
	struct {
		unsigned DS:4;
		unsigned RSVD4_7:4;
		unsigned MA:8;
		unsigned reserved16_31:16;
	} lpddr3; /* MR2 */
};

union ddr_mr10 {
	/** raw register data */
	unsigned int d32;
	/** register bits */
	struct {
		unsigned CAL_CODE:8;
		unsigned MA:8;
		unsigned reserved16_31:16;
	} lpddr2; /* MR_RST */
	struct {
		unsigned CAL_CODE:8;
		unsigned MA:8;
		unsigned reserved16_31:16;
	} lpddr3; /* MR_RST */
};

union ddr_mr11 {
	/** raw register data */
	unsigned int d32;
	/** register bits */
	struct {
		unsigned ODT:2;
		unsigned PD:1;
		unsigned RSVD3_7:5;
		unsigned MA:8;
		unsigned reserved16_31:16;
	} lpddr3; /* MR_ODT */
};

union ddr_mr63 {
	/** raw register data */
	unsigned int d32;
	/** register bits */
	struct {
		unsigned RSVD0_7:8;
		unsigned MA:8;
		unsigned reserved16_31:16;
	} lpddr2; /* MR_IO_CALIBRATION */
	struct {
		unsigned RST:8;
		unsigned MA:8;
		unsigned reserved16_31:16;
	} lpddr3; /* MR_IO_CALIBRATION */
};

#endif

struct ddr_params {
	unsigned int type;
	unsigned int freq;
	unsigned int div;
	unsigned int cs0;
	unsigned int cs1;
	unsigned int dw32;
	unsigned int cl;
	unsigned int bl;
	unsigned int col;
	unsigned int row;
	unsigned int col1;
	unsigned int row1;
	unsigned int bank8;
	struct size size;
	union private_params private_params;
#ifdef CONFIG_DDR_INNOPHY
	union ddr_mr0 mr0;
	union ddr_mr1 mr1;
	union ddr_mr2 mr2;
	union ddr_mr3 mr3;
	union ddr_mr10 mr10;
	union ddr_mr11 mr11;
	union ddr_mr63 mr63;
#endif
};
/*
 * DDR Controller common data structure.
 */
typedef union ddrc_timing1 {
	/** raw register data */
	unsigned int d32;
	/** register bits */
	struct {
		unsigned tWL:6;
		unsigned reserved6_7:2;
		unsigned tWR:6;
		unsigned reserved14_15:2;
		unsigned tWTR:6;
		unsigned reserved22_23:2;
		unsigned tWDLAT:6;
		unsigned reserved30_31:2;
	} b;
} ddrc_timing1_t;

typedef union ddrc_timing2 {
	/** raw register data */
	unsigned int d32;
	/** register bits */
	struct {
		unsigned tRL:6;
		unsigned reserved6_7:2;
		unsigned tRTP:6;
		unsigned reserved14_15:2;
		unsigned tRTW:6;
		unsigned reserved22_23:2;
		unsigned tRDLAT:6;
		unsigned reserved30_31:2;
	} b;

} ddrc_timing2_t;

typedef union ddrc_timing3 {
	/** raw register data */
	unsigned int d32;
	/** register bits */
	struct {
		unsigned tRP:6;
		unsigned reserved6_7:2;
		unsigned tCCD:6;
		unsigned reserved14_15:2;
		unsigned tRCD:6;
		unsigned reserved22_23:2;
		unsigned tEXTRW:3;
		unsigned reserved27_31:5;
	} b;
} ddrc_timing3_t;

typedef union ddrc_timing4 {
	/** raw register data */
	unsigned int d32;
	/** register bits */
	struct {
		unsigned tRRD:6;
		unsigned reserved6_7:2;
		unsigned tRAS:6;
		unsigned reserved14_15:2;
		unsigned tRC:6;
		unsigned reserved22_23:2;
		unsigned tFAW:8;
	} b;
} ddrc_timing4_t;

typedef union ddrc_timing5 {
	/** raw register data */
	unsigned int d32;
	/** register bits */
	struct {
		unsigned tCKE:3;
		unsigned reserved3:1;
		unsigned tXP:4;
		unsigned reserved8_11:4;
		unsigned tCKSRE:4;
		unsigned tCKESR:8;
		unsigned tXS:8;
	} b;
} ddrc_timing5_t;

typedef union ddrc_cfg {
	/** raw register data */
	unsigned int d32;
	/** register bits */
	struct {
		unsigned CS0EN:1;
		unsigned CS1EN:1;
		unsigned ODTEN:1;
		unsigned TYPE:3;
		unsigned reserved6_8:3;
		unsigned BA0:1;
		unsigned COL0:3;
		unsigned ROW0:3;
		unsigned IMBA:1;
		unsigned reserved17_24:8;
		unsigned BA1:1;
		unsigned COL1:3;
		unsigned ROW1:3;
	} b;
} ddrc_cfg_t;

struct ddrc_reg {
	ddrc_cfg_t cfg;
	unsigned int ctrl;
	unsigned int ddlp;
	unsigned int refcnt;
	unsigned int dlmr;
	unsigned int mmap[2];
	unsigned int remap[5];
	ddrc_timing1_t timing1;
	ddrc_timing2_t timing2;
	ddrc_timing3_t timing3;
	ddrc_timing4_t timing4;
	ddrc_timing5_t timing5;
	unsigned int autosr_cnt;
	unsigned int autosr_en;
	unsigned int hregpro;
	unsigned int pregpro;
	unsigned int cguc0;
	unsigned int cguc1;
};

typedef unsigned int u32;
typedef u32 phys_size_t;

/*
 * DDR parameters data structure.
 */
enum ddr_type{
	DDR3,
	LPDDR,
	LPDDR2,
	LPDDR3,
	DDR2,
	VARIABLE,
	UNKOWN,
};

/* ----------------------- */

/*************************************************************************
 * DDR Controller Registers
 *************************************************************************/

#define DDRC_APB_OFFSET         (-0x4e0000 + 0x2000)
#define DDR_PHY_OFFSET          (-0x4e0000 + 0x1000)


#define DDRC_STATUS         0x0
#define DDRC_CFG            0x8
#define DDRC_CTRL           0x10
#define DDRC_LMR            0x18
#define DDRC_DLP            0x20
#define DDRC_AUTOSR_EN      0x28
#define DDRC_AUTOSR_CNT     0x30
#define DDRC_REFCNT         0x38
#define DDRC_TIMING(n)      (0x40 + 8 * (n - 1))
#define DDRC_MMAP0          0x78
#define DDRC_MMAP1          0x80
#define DDRC_BWCFG          0x88
#define DDRC_BWSTP          0x90
#define DDRC_BWP0WR         0x98
#define DDRC_BWP1WR         0xa8
#define DDRC_BWP2WR         0xb8
#define DDRC_BWP3WR         0xc8
#define DDRC_HREGPRO        0xd8
#define DDRC_DBGEN          0xE0
#define DDRC_DBGINFO        0xE8
#define DDRC_DWCFG          (DDRC_APB_OFFSET + 0x00)
#define DDRC_DWSTATUS       (DDRC_APB_OFFSET + 0x04)
#define DDRC_REMAP(n)       (DDRC_APB_OFFSET + 0x08 + 4 * (n - 1))
#define DDRC_CPAC           (DDRC_APB_OFFSET + 0x1c)
#define DDRC_CCHC(n)        (DDRC_APB_OFFSET + 0x20 + 4 * (n - 1))
#define DDRC_CSCHC(n)       (DDRC_APB_OFFSET + 0x40 + 4 * (n - 1))
#define DDRC_CMONC(n)       (DDRC_APB_OFFSET + 0x50 + 4 * (n - 1))
#define DDRC_CGUC0          (DDRC_APB_OFFSET + 0x64)
#define DDRC_CGUC1          (DDRC_APB_OFFSET + 0x68)
#define DDRC_PREGPRO        (DDRC_APB_OFFSET + 0x6c)
#define DDRC_BUFCFG         (DDRC_APB_OFFSET + 0x70)

/*************************************************************************
 * DDRP (DDR Innophy registers)
 *************************************************************************/

#define DDRP_INNOPHY_INNO_PHY_RST   (DDR_PHY_OFFSET + 0x000)
#define DDRP_INNOPHY_MEM_CFG        (DDR_PHY_OFFSET + 0x004)
#define DDRP_INNOPHY_TRAINING_CTRL  (DDR_PHY_OFFSET + 0x008)
#define DDRP_INNOPHY_INNO_WR_LEVEL1 (DDR_PHY_OFFSET + 0x00c)
#define DDRP_INNOPHY_INNO_WR_LEVEL2 (DDR_PHY_OFFSET + 0x010)
#define DDRP_INNOPHY_CL             (DDR_PHY_OFFSET + 0x014)
#define DDRP_INNOPHY_AL             (DDR_PHY_OFFSET + 0x018)
#define DDRP_INNOPHY_CWL            (DDR_PHY_OFFSET + 0x01c)
#define DDRP_INNOPHY_DQ_WIDTH       (DDR_PHY_OFFSET + 0x07c)
#define DDRP_INNOPHY_PLL_FBDIV      (DDR_PHY_OFFSET + 0x080)
#define DDRP_INNOPHY_PLL_CTRL       (DDR_PHY_OFFSET + 0x084)
#define DDRP_INNOPHY_PLL_PDIV       (DDR_PHY_OFFSET + 0x088)
#define DDRP_INNOPHY_WL_DONE        (DDR_PHY_OFFSET + 0x100)
#define DDRP_INNOPHY_DLL_LOCK       (DDR_PHY_OFFSET + 0x104)
#define DDRP_INNOPHY_PLL_LOCK       (DDR_PHY_OFFSET + 0x108)
#define DDRP_INNOPHY_CALIB_DONE     (DDR_PHY_OFFSET + 0x10c)
#define DDRP_INNOPHY_INIT_COMP      (DDR_PHY_OFFSET + 0x110)
#define DDRP_INNOPHY_BIST_RES       (DDR_PHY_OFFSET + 0x118)

#define DDRP_INNOPHY_CALIB_DELAY_AL_RESULT  (DDR_PHY_OFFSET + 0x1d0)//0x74
#define DDRP_INNOPHY_CALIB_DELAY_AH_RESULT  (DDR_PHY_OFFSET + 0x1d4)//0x75
#define DDRP_INNOPHY_CALIB_DELAY_BL_RESULT  (DDR_PHY_OFFSET + 0x290)//0xA4
#define DDRP_INNOPHY_CALIB_DELAY_BH_RESULT  (DDR_PHY_OFFSET + 0x294)//0xA5

#define DDRP_INNOPHY_CALIB_DELAY_AL         (DDR_PHY_OFFSET + 0x158)//0x56
#define DDRP_INNOPHY_CALIB_DELAY_AH         (DDR_PHY_OFFSET + 0x198)//0x66
#define DDRP_INNOPHY_CALIB_BYPASS_AL        (DDR_PHY_OFFSET + 0x17c)//0x5f
#define DDRP_INNOPHY_CALIB_BYPASS_AH        (DDR_PHY_OFFSET + 0x23c)//0x8f
#define DDRP_INNOPHY_CALIB_DELAY_BL         (DDR_PHY_OFFSET + 0x218)//0x86
#define DDRP_INNOPHY_CALIB_DELAY_BH         (DDR_PHY_OFFSET + 0x258)//0x96
#define DDRP_INNOPHY_WL_MODE1               (DDR_PHY_OFFSET + 0x00c)
#define DDRP_INNOPHY_WL_MODE2               (DDR_PHY_OFFSET + 0x010)
#define DDRP_INNOPHY_WL_DONE                (DDR_PHY_OFFSET + 0x100)

#define DDRP_INNOPHY_TRAINING_2c            (DDR_PHY_OFFSET + 0x0b0)
#define DDRP_INNOPHY_TRAINING_3c            (DDR_PHY_OFFSET + 0x0f0)
#define DDRP_INNOPHY_TRAINING_4c            (DDR_PHY_OFFSET + 0x130)
#define DDRP_INNOPHY_TRAINING_5c            (DDR_PHY_OFFSET + 0x170)

#define DDRP_INNOPHY_WRLEVEL_RESULT1        (DDR_PHY_OFFSET + 0x1c0)
#define DDRP_INNOPHY_WRLEVEL_RESULT2        (DDR_PHY_OFFSET + 0x170)



/*************************************************************************
 * DDRC REGISTER BITS DEFINE
 *************************************************************************/

/* DDRC Status Register */
#define DDRC_DSTATUS_MISS   (1 << 6)
#define DDRC_ST_DPDN        (1 << 5) /* 0 DDR memory is NOT in deep-power-down state
                                        1 DDR memory is in deep-power-down state */
#define DDRC_ST_PDN         (1 << 4) /* 0 DDR memory is NOT in power-down state
                                        1 DDR memory is in power-down state */
#define DDRC_ST_AREF        (1 << 3) /* 0 DDR memory is NOT in auto-refresh state
                                        1 DDR memory is in auto-refresh state */
#define DDRC_ST_SREF        (1 << 2) /* 0 DDR memory is NOT in self-refresh state
                                        1 DDR memory is in self-refresh state */
#define DDRC_ST_CKE1        (1 << 1) /* 0 CKE1 Pin is low
                                        1 CKE1 Pin is high */
#define DDRC_ST_CKE0        (1 << 0) /* 0 CKE0 Pin is low
                                        1 CKE0 Pin is high */

/* DDRC Configure Register */
#define DDRC_CFG_ROW1_BIT       29 /* Row Address width. */
#define DDRC_CFG_ROW1_MASK      (0x7 << DDRC_CFG_ROW1_BIT)
#define DDRC_CFG_COL1_BIT       26 /* Row Address width. */
#define DDRC_CFG_COL1_MASK      (0x7 << DDRC_CFG_COL1_BIT)
#define DDRC_CFG_BA1            25 /* Bank Address width of DDR memory */
#define DDRC_CFG_IMBA           (1 << 16)
#define DDRC_CFG_ROW0_BIT       13 /* Row Address width. */
#define DDRC_CFG_ROW0_MASK      (0x7 << DDRC_CFG_ROW0_BIT)
#define DDRC_CFG_COL0_BIT       10 /* Row Address width. */
#define DDRC_CFG_COL0_MASK      (0x7 << DDRC_CFG_COL1_BIT)
#define DDRC_CFG_BA0            9 /* Bank Address width of DDR memory */

#define DDRC_CFG_TYPE_BIT       3
#define DDRC_CFG_TYPE_MASK      (0x7 << DDRC_CFG_TYPE_BIT)
#define DDRC_CFG_TYPE_DDR1      (2 << DDRC_CFG_TYPE_BIT)
#define DDRC_CFG_TYPE_MDDR      (3 << DDRC_CFG_TYPE_BIT)
#define DDRC_CFG_TYPE_DDR2      (4 << DDRC_CFG_TYPE_BIT)
#define DDRC_CFG_TYPE_LPDDR2    (5 << DDRC_CFG_TYPE_BIT)
#define DDRC_CFG_TYPE_DDR3      (6 << DDRC_CFG_TYPE_BIT)
#define DDRC_CFG_TYPE_LPDDR3    (7 << DDRC_CFG_TYPE_BIT)

#define DDRC_CFG_ODTEN          (1 << 2)  /* ODT EN */
#define DDRC_CFG_CS1EN          (1 << 1)  /* DDR Chip-Select-1 Enable */
#define DDRC_CFG_CS0EN          (1 << 0)  /* DDR Chip-Select-0 Enable */

/* DDRC Control Register */
#define DDRC_CTRL_DFI_RST       (1 << 23)
#define DDRC_CTRL_DLL_RST       (1 << 22)//reserve
#define DDRC_CTRL_CTL_RST       (1 << 21)//reserve
#define DDRC_CTRL_CFG_RST       (1 << 20)
#define DDRC_CTRL_ACTPD         (1 << 15) /* 0 Precharge all banks before entering power-down
					     1 Do not precharge banks before entering power-down */
#define DDRC_CTRL_PDT_BIT       12 /* Power-Down Timer */
#define DDRC_CTRL_PDT_MASK      (0x7 << DDRC_CTRL_PDT_BIT)
#define DDRC_CTRL_PDT_DIS       (0 << DDRC_CTRL_PDT_BIT) /* power-down disabled */
#define DDRC_CTRL_PDT_8         (1 << DDRC_CTRL_PDT_BIT) /* Enter power-down after 8 tCK idle */
#define DDRC_CTRL_PDT_16        (2 << DDRC_CTRL_PDT_BIT) /* Enter power-down after 16 tCK idle */
#define DDRC_CTRL_PDT_32        (3 << DDRC_CTRL_PDT_BIT) /* Enter power-down after 32 tCK idle */
#define DDRC_CTRL_PDT_64        (4 << DDRC_CTRL_PDT_BIT) /* Enter power-down after 64 tCK idle */
#define DDRC_CTRL_PDT_128       (5 << DDRC_CTRL_PDT_BIT) /* Enter power-down after 128 tCK idle */

#define DDRC_CTRL_PD_CCE        (1 << 7) /* Power down clk freq change enable */
#define DDRC_CTRL_DPD           (1 << 6) /* 1 Drive external MDDR device entering Deep-Power-Down mode */
#define DDRC_CTRL_SR            (1 << 5) /* 1 Drive external DDR device entering self-refresh mode
                                            0 Drive external DDR device exiting self-refresh mode */
#define DDRC_CTRL_SR_CCE        (1 << 4) /* Self refresh clk stop request enable */
#define DDRC_CTRL_CKE           (1 << 1) /* 0 Not set CKE Pin High, 1 Set CKE Pin HIGH */
#define DDRC_CTRL_RESET         (1 << 0) /* 0 End resetting ddrc_controller, 1 Resetting ddrc_controller */

/* DDRC DFI low power handshake control register */
#define DDRC_DDLP_TCTLUDP_BIT   24
#define DDRC_DDLP_TCTLUDP_FF    (0xff << DDRC_DDLP_TCTLUDP_BIT)

/* DDRC Load-Mode-Register */
#define DDRC_LMR_DDR_ADDR_BIT   12 /* When performing a DDR command, DDRC_ADDR[13:0]
				      corresponding to external DDR address Pin A[13:0] */
#define DDRC_LMR_DDR_ADDR_MASK  (0xfffff << DDRC_LMR_DDR_ADDR_BIT)

#define DDRC_LMR_MA_BIT         16 /* FOR LPDDR2, MA[9:0] */
#define DDRC_LMR_OP_BIT         24 /* FOR LPDDR2, OP[9:0] */

#define DDRC_LMR_BA_BIT         9 /* When performing a DDR command, BA[2:0]
				     corresponding to external DDR address Pin BA[2:0]. */
#define DDRC_LMR_BA_MASK        (0x7 << DDRC_LMR_BA_BIT)
#define DDRC_LMR_CMD_BIT        6
#define DDRC_LMR_CMD_MASK       (0x7 << DDRC_LMR_CMD_BIT)
#define DDRC_LMR_CMD_PREC       (0 << DDRC_LMR_CMD_BIT)/* Precharge one bank/All banks */
#define DDRC_LMR_CMD_AUREF      (1 << DDRC_LMR_CMD_BIT)/* Auto-Refresh */
#define DDRC_LMR_CMD_LMR        (2 << DDRC_LMR_CMD_BIT)/* Load Mode Register */
#define DDRC_LMR_CMD_ZQCL_CS0   (3 << DDRC_LMR_CMD_BIT)/* ZQCL for DDR3 on CS0 */
#define DDRC_LMR_CMD_ZQCL_CS1   (4 << DDRC_LMR_CMD_BIT)/* ZQCL for DDR3 on CS1 */
#define DDRC_LMR_CMD_ZQCS_CS0   (5 << DDRC_LMR_CMD_BIT)/* ZQCS for DDR3 on CS0 */
#define DDRC_LMR_CMD_ZQCS_CS1   (6 << DDRC_LMR_CMD_BIT)/* ZQCS for DDR3 on CS1 */

#define DDRC_LMR_TMRD_BIT       1
#define DDRC_LMR_TMRD_MASK      (0x1f << DDRC_LMR_TMRD_BIT)
#define DDRC_LMR_START          (1 << 0) /* 0 No command is performed
                                            1 On the posedge of START, perform a command
                                            defined by CMD field */

/* DDRC  Auto-Refresh Counter */
#define DDRC_REFCNT_REF_EN          (1 << 0) /* Enable Refresh Counter */
#define DDRC_REFCNT_CLK_DIV_BIT     1  /* Clock Divider for auto-refresh counter. */
#define DDRC_REFCNT_CLK_DIV_MASK    (0x7 << DDRC_REFCNT_CLKDIV_BIT)

#define DDRC_REFCNT_PREREF_CNT_BIT      4
#define DDRC_REFCNT_PREREF_CNT_MASK     (0xf << DDRC_REFCNT_PREREF_CNT_BIT)
#define DDRC_REFCNT_PREREF_CNT(val)     (val << DDRC_REFCNT_PREREF_CNT_BIT)
#define DDRC_REFCNT_PREREF_CNT_DEFAULT  DDRC_REFCNT_PREREF_CNT(8)

#define DDRC_REFCNT_CNT_BIT         8  /* 8-bit counter */
#define DDRC_REFCNT_CNT_MASK        (0xff << DDRC_REFCNT_CNT_BIT)

#define DDRC_REFCNT_CON_BIT         16 /* Constant value used to compare with CNT value. */
#define DDRC_REFCNT_CON_MASK        (0xff << DDRC_REFCNT_CON_BIT)

#define DDRC_REFCNT_TRFC_BIT        24
#define DDRC_REFCNT_TRFC_MASK       (0x3f << DDRC_REFCNT_TRFC_BIT)

#define DDRC_REFCNT_PREREF_EN_BIT   30
#define DDRC_REFCNT_PREREF_EN       (1 << DDRC_REFCNT_PREREF_EN_BIT)

#define DDRC_REFCNT_PBREF_EN_BIT    31
#define DDRC_REFCNT_PBREF_EN        (1 << DDRC_REFCNT_PBREF_EN_BIT)

/* DDRC Memory Map Config Register */
#define DDRC_MMAP_BASE_BIT          8 /* base address */
#define DDRC_MMAP_BASE_MASK         (0xff << DDRC_MMAP_BASE_BIT)
#define DDRC_MMAP_MASK_BIT          0 /* address mask */
#define DDRC_MMAP_MASK_MASK         (0xff << DDRC_MMAP_MASK_BIT)

#define DDRC_MMAP0_BASE             (0x20 << DDRC_MMAP_BASE_BIT)
#define DDRC_MMAP1_BASE_64M         (0x24 << DDRC_MMAP_BASE_BIT) /*when bank0 is 128M*/
#define DDRC_MMAP1_BASE_128M        (0x28 << DDRC_MMAP_BASE_BIT) /*when bank0 is 128M*/
#define DDRC_MMAP1_BASE_256M        (0x30 << DDRC_MMAP_BASE_BIT) /*when bank0 is 128M*/

#define DDRC_MMAP_MASK_64_64        (0xfc << DDRC_MMAP_MASK_BIT)  /*mask for two 128M SDRAM*/
#define DDRC_MMAP_MASK_128_128      (0xf8 << DDRC_MMAP_MASK_BIT)  /*mask for two 128M SDRAM*/
#define DDRC_MMAP_MASK_256_256      (0xf0 << DDRC_MMAP_MASK_BIT)  /*mask for two 128M SDRAM*/

/* DDR device data width configure register */
#define DDRC_DWCFG_DFI_INIT_START   (1 << 3)

/* DDR device status register */
#define DDRC_DWSTATUS_DFI_INIT_COMP (1 << 0)

/* DDRC AHB Bus Register Protection Register */
#define DDRC_HREGPRO_HPRO_EN        (1 << 0)

/* DDRC APB Bus Register Protection Register */
#define DDRC_PREGPRO_PPRO_EN        (1 << 0)


/* DDRC clock gate unit configure 0 */
#define DDRC_CGU_PORT7      (1 << 28)
#define DDRC_CGU_PORT6      (1 << 24)
#define DDRC_CGU_PORT5      (1 << 20)
#define DDRC_CGU_PORT4      (1 << 16)
#define DDRC_CGU_PORT3      (1 << 12)
#define DDRC_CGU_PORT2      (1 << 8)
#define DDRC_CGU_PORT1      (1 << 4)
#define DDRC_CGU_PORT0      (1 << 0)

/* DDRC clock gate unit configure 1 */
#define DDRC_CGU_BWM        (1 << 8)
#define DDRC_CGU_PCTRL      (1 << 4)
#define DDRC_CGU_SCH        (1 << 1)
#define DDRC_CGU_PA         (1 << 0)


	/**************************************
	 * DDR INNOPHY REGISTER BITS DEFINE
	 **************************************/

	/* DDRP DQ Width Register */
#define DDRP_DQ_WIDTH_DQ_H      (1 << 1)
#define DDRP_DQ_WIDTH_DQ_L      (1 << 0)

	/* DDRP Pll Ctrl Register */
#define DDRP_PLL_CTRL_PLLPDEN           (1 << 1)

/* DDRP Training Ctrl Register */
#define DDRP_TRAINING_CTRL_WL_BP        (1 << 3)
#define DDRP_TRAINING_CTRL_WL_START     (1 << 2)
#define DDRP_TRAINING_CTRL_DSCSE_BP     (1 << 1)
#define DDRP_TRAINING_CTRL_DSACE_START  (1 << 0)

/* DDRP Training Done Register */
#define DDRP_CALIB_DONE_HDQCFB      (1 << 3)
#define DDRP_CALIB_DONE_LDQCFB      (1 << 2)
#define DDRP_CALIB_DONE_HDQCFA      (1 << 1)
#define DDRP_CALIB_DONE_LDQCFA      (1 << 0)
#define DDRP_CALIB_DONE_HWRLFB      (1 << 3)
#define DDRP_CALIB_DONE_LWRLFB      (1 << 2)
#define DDRP_CALIB_DONE_HWRLFA      (1 << 1)
#define DDRP_CALIB_DONE_LWRLFA      (1 << 0)

/* DDRP CALIB BP Register */
#define DDRP_CALIB_BP_CYCLESELBH_BIT    4
#define DDRP_CALIB_BP_OPHCSELBH_BIT     3
#define DDRP_CALIB_BP_DLLSELBH_BIT      0

/* DDRP Init Complete Register */
#define DDRP_INIT_COMP          (1 << 0)

/* DDRP PLL LOCK Register */
#define DDRP_PLL_LOCK           (1 << 3)

extern unsigned int __ps_per_tck;

#define DDR_SELECT_MAX__tCK_ps(tck, ps)					\
	({								\
		unsigned int value;					\
		value = (tck * __ps_per_tck > ps) ? (tck * __ps_per_tck) : ps; \
		value;							\
	})

#define DDR__ns(ns)   (ns * 1000)
#define DDR__ps(ps)   (ps)
#define DDR__tck(tck) (tck * __ps_per_tck)

struct jzsoc_ddr_hook
{
	void (*prev_ddr_init)(enum ddr_type type);
	void (*post_ddr_init)(enum ddr_type type);
};
void register_ddr_hook(struct jzsoc_ddr_hook * hook);

#define timing1_tWL     1
#define timing1_tWR     8
#define timing1_tWTR        8
#define timing1_tWDLAT      1
#define timing2_tRL     3
#define timing2_tRTP        4
#define timing2_tRTW        8
#define timing2_tRDLAT      1
#define timing3_tRP     11
#define timing3_tCCD        2
#define timing3_tRCD        9
#define timing3_ttEXTRW     3
#define timing4_tRRD        5
#define timing4_tRAS        21
#define timing4_tRC         32
#define timing4_tFAW        25
#define timing5_tCKE        3
#define timing5_tXP         4
#define timing5_tCKSRE      2
#define timing5_tCKESR      8
#define timing5_tXS         18
#define REMMAP_ARRAY {				\
		0x030e0d0c,			\
			0x07060504,		\
			0x0b0a0908,		\
			0x0f020100,		\
			0x13121110,		\
			};
//#define DDRC_CFG_VALUE          0x92009235
#define DDRC_CFG_VALUE          0x6a006a35
#define DDRC_CTRL_VALUE         0x0000b092
#define DDRC_DLMR_VALUE         0x00000002
#define DDRC_DDLP_VALUE         0x00000000
#define DDRC_MMAP0_VALUE        0x00000000
//#define DDRC_MMAP0_VALUE        0x000020e0
#define DDRC_MMAP1_VALUE        0x00004000
#define DDRC_REFCNT_VALUE       0x60c20081
#define DDRC_TIMING1_VALUE      0x040d0605
#define DDRC_TIMING2_VALUE      0x03070406
#define DDRC_TIMING3_VALUE      0x03060406
#define DDRC_TIMING4_VALUE      0x12151004
#define DDRC_TIMING5_VALUE      0x80045043
#define DDRC_AUTOSR_CNT_VALUE   0x20000c30
#define DDRC_AUTOSR_EN_VALUE    0x00000000
#define DDRC_HREGPRO_VALUE      0x00000001
#define DDRC_PREGPRO_VALUE      0x00000001
#define DDRC_CGUC0_VALUE        0x11111111
#define DDRC_CGUC1_VALUE        0x00000113
#define DDRP_MEMCFG_VALUE       0x00000010
#define DDRP_CL_VALUE           0x00000006
#define DDRP_CWL_VALUE          0x00000008
#define DDR_MR0_VALUE           0x00001520
#define DDR_MR1_VALUE           0x00010006
#define DDR_MR2_VALUE           0x00020000
#define DDR_MR3_VALUE           0x00030000
#define DDR_MR10_VALUE          0x00000000
#define DDR_MR63_VALUE          0x00000000
#define DDR_CHIP_0_SIZE         536870912
#define DDR_CHIP_1_SIZE         0

void ddr_init(int);

#endif /* __DDR__H__ */
